<?php
/*******************************************************************************

    FinalsClub.org is a platform for students and faculty to collaborate
    and share their knowledge with the world.

    Copyright (C) 2009  Andrew Magliozzi
 
    This file is a part of FinalsClub.org.

    FinalsClub.org is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
    To contact FinalsClub.org, send an email to info@finalsclub.org, or
    send mail to Finals Club, c/o Veritas Tutors, 1132 Massachusetts Avenue,
    Cambridge, MA 02138.

*******************************************************************************/

class EntitlementPeer {
	const READ_PERMISSION = 'r';
	const WRITE_PERMISSION = 'w';
	
	const ADMIN_ROLE = '1';
	const CONTRIBUTOR_ROLE = '2';
	const VIEWER_ROLE = '3';

	const NOTE_TYPE = 'note';
	const GROUP_TYPE = 'group';
	const NETWORK_TYPE = 'network';
	const FILE_TYPE = 'file';
	const MESSAGE_TYPE = 'message';
	const SUMMARY_TYPE = 'summary';
	const TASK_TYPE = 'task';
	const ANNOTATION_TYPE = 'annotation';
	
	/**
	 * overarching static method which is to be used to detemine if a user is entitled (allowed) to access the referencing item
	 *
	 * @param $resource_id - the id of whatever it is that is being checked to see if it is allowed to be accessed
   	 * @param $user_id - the id of the user in question
	 * @param $resource_type - the type of check this is (see the above types: note_type, group_type, network_type, etc). if none is
	 *					provided then we assume 'note_type'
	 * @param $permission - type of permission to check (read_permission, write_permission).  Defaults to read_permission
	 *
	 * @return    boolean - true = isentitled, false - is not
	 */
	public static function isEntitled($resource_id, $user_id, $resource_type=EntitlementPeer::NOTE_TYPE,$permission=EntitlementPeer::READ_PERMISSION) {
		$user = UserPeer::retrieveById($user_id);		
		if($user && $user->getAdmin()) {	// return true, if the user is a global admin
			return true;
		} 

		return call_user_func_array('EntitlementPeer::'.$resource_type.'Entitled', array($resource_id,$user_id, $permission));
	}
	
	private static function noteEntitled($id, $user_id, $permission=EntitlementPeer::READ_PERMISSION) {
		$c = new Criteria();
		$c->add(NotePeer::ID, $id);
		$note = NotePeer::doSelectJoinAll($c);

		if($note) {
			$note = $note[0];	// grab the first and only entry

			$visibility = $note->getVisibility();
			if($visibility == NotePeer::EVERYONE) {
				return true; // permission is for everyone
			}

			if($note->getUserId() == $user_id) return true;
			if(!self::profAdminEntitled("note", $id, $user_id)) return false;			

			$user = UserPeer::retrieveById($user_id);
			if($user->isAdminOf($note->getCourseId())) return true;

			$course = $note->getCourse();
			// check network level
			if($visibility == NotePeer::SCHOOL && $course && $course->getNetworkId() == $user->getNetworkId()) {
				if($permission == EntitlementPeer::READ_PERMISSION) {
					return true;
				} 
			}			

			$group_member = GroupMemberPeer::retrieveByUserIdAndGroupId($user_id, $note->getGroupId());
			if($visibility == NotePeer::GROUP && $group_member) {
				if($permission == EntitlementPeer::READ_PERMISSION) {
					return true;
				} 
			}

			if($permission == EntitlementPeer::WRITE_PERMISSION
				&& $group_member && $group_member->getRole() >= GroupMemberPeer::CONTRIBUTOR) {
				return true;
			} 		
		} else {
			// note does not exist
			return false;
		}
		return false; // catch all
	}

	private static function fileEntitled($file_id, $user_id, $permission=EntitlementPeer::READ_PERMISSION) {
		$file = FilePeer::retrieveByPK($file_id);

		if(!$file) {
			return false;  // file doesnt exist
		}

		$file_permission = $file->getPermissionLevel();

		if($file->getOwnerId() == $user_id || $file_permission == FilePeer::PUBLIC_PERMISSION) {
			return true;
		}

		$user = UserPeer::retrieveById($user_id);
		
		//if file is associated with a course and has network permission levels
		if($file->getCourseId() && $file_permission == FilePeer::NETWORK_PERMISSION)
		{
			$course = CoursePeer::retrieveById();

			if($course->getNetworkId() == $user->getNetworkId()) 
			{
				return true;
			}
			else
			{
				return false;
			}
			
		}

		if($file_permission == FilePeer::PRIVATE_PERMISSION) {  // already checked for owner so it that failed then if private will fail
			return false;
		}

		if($file_permission == FilePeer::GROUP_PERMISSION || $file_permission == FilePeer::INTERNAL_PERMISSION) {
			if($file->getGroupId() != null) {
				if(EntitlementPeer::groupEntitled($file->getGroupId(), $user_id, $permission)) {
					return true;	
				}
				return false;
			} else if($file_permission == FilePeer::GROUP_PERMISSION) {
				return false;
			}
		}

		if($file_permission == FilePeer::NETWORK_PERMISSION || $file_permission == FilePeer::INTERNAL_PERMISSION) {
			return EntitlementPeer::networkEntitled($file->getNetworkId(), $user_id, $permission);
		}

		return true;
	}

	private static function groupEntitled($group_id, $user_id, $permission=EntitlementPeer::READ_PERMISSION) {
		$group_member = GroupMemberPeer::retrieveByUserIdAndGroupId($user_id, $group_id);
		if($group_member && $permission == EntitlementPeer::READ_PERMISSION) {
			return true;
		} else if($group_member && $permission == EntitlementPeer::WRITE_PERMISSION 
			&& $group_member->getRole() >= GroupMemberPeer::CONTRIBUTOR) {
			return true;		
		} else {
			return false;
		}
		
	}

	private static function networkEntitled($network_id, $user_id, $permission=EntitlementPeer::READ_PERMISSION) {
		$user = UserPeer::retrieveById($user_id);	
		if(!$user) return false;
		if($network_id == $user->getNetworkId()) {
			return true;
		}
		return false;
	}
	
	
	private static function messageEntitled($message_id, $user_id, $permission=EntitlementPeer::READ_PERMISSION) {
		
		
		$message = MessagePeer::retrieveById($message_id);
		if(!$message) return false;
		
	   if($message->getSenderId() == $user_id || $message->getRecipientId() == $user_id)
		{
			//if user is sender or recipient then give them permission
			return true;
		}
		else if($message->getType() == MessagePeer::GROUP_TYPE)
		{
			$group_id = $message->getTypeId();

			//check the entitlement of the group of this message
			return EntitlementPeer::groupEntitled($group_id, $user_id, $permission);
		}
			
		//user messages are not handled yet
		return false;
		
	}
	
	private static function summaryEntitled($summary_id, $user_id, $permission=EntitlementPeer::READ_PERMISSION) {
			
		$summary = SummaryPeer::retrieveById($summary_id);
		
		if(!$summary) return false;
		
		//Course admin stuff
		$user = UserPeer::retrieveByPK($user_id);
		if(!$user && !$summary->getGroupId()  && $permissions == EntitlementPeer::READ_PERMISSION) return true;

		if($user->isAdminOf($summary->getCourseId()))
			return true;
			
		//if user is the creator then default true
		if($summary->getUserId() == $user_id)
		{
			return true;
		}

		if(!self::profAdminEntitled("summary", $summary_id, $user_id))
			return false;
		
		if($summary->getGroupId())
		{
			//if the user has the correct group permission level then return true
			return EntitlementPeer::groupEntitled($summary->getGroupId(), $user_id, $permission);
			
		}
				
		if($permissions == EntitlementPeer::READ_PERMISSION)
		{	//all users can read a summary if it is not associated with a group
			return true;
		}
		
		return false;		
	}
	
	private static function taskEntitled($task_id, $user_id, $permission=EntitlementPeer::READ_PERMISSION) {
		$task = TaskPeer::retrieveById($task_id);
		if(!$task) return false;
		return EntitlementPeer::groupEntitled($task->getGroupId(),$user_id, $permission);	
	}
	
	private static function annotationEntitled($annotation_id, $user_id, $permission=EntitlementPeer::READ_PERMISSION) {
		$annotation = AnnotationPeer::retrieveByPK($annotation_id);
		if(!$annotation) return false;
		if(!self::profAdminEntitled("annotation", $summary_id, $user_id) && $user_id != $annotation->getUserId())
			return false;
			
		return true;
	}
	
	//Prof Admin stuff
	
	private static function profAdminEntitled($type,$type_id, $user_id){
		$user = UserPeer::retrieveByPK($user_id);
		if(!$user) return false;
		if($type === "note"){
			$note = NotePeer::retrieveByPK($type_id);
			$course = $note->getCourse();
		}else if( $type === "summary"){
			$summary = SummaryPeer::retrieveByPK($type_id);
			$course = $summary->getCourse();
		}else if( $type === "annotation" ){
			$annot = AnnotationPeer::retrieveByPK($type_id);
			$course = $annot->getNote()->getCourse();
		}else
			return true;
		
		if($user->isAdminOf($course->getId()))
			return true;
		//no prof for this course yet
		if(!$course->getInstructorEmail())
			return true;
			
		$prof_user = UserPeer::retrieveByEmail($course->getInstructorEmail());

		if(!$prof_user) return true; // no prof/user retrieved with that email - potential issue with user/course email mismatch
		
		$prof = $prof_user->getProf();
		
		//has prof prohibited external viewing of course material?
		if(!$prof->getCourseMaterialExternalVisibility() && $user->getNetworkId() != $course->getNetworkId())
			return false;
			
		return true;
	}
	
}
